﻿using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Shell.Interop;
using PowerGui.AddOn.Impl;
using PowerGuiVsx.Interfaces;

namespace PowerGuiVsx.Core
{
    [Export(typeof(IDebuggerLauncher))]
    class DebuggerLauncher : IDebuggerLauncher
    {
        [Import]
        public PowerShellDebugger Debugger { get; set; }

        [Import]
        internal ConfigLoader ConfigLoader { get; set; }


        public void LaunchDebugger(IVsUIShell shell, IVsDebugger debugger, IEditorFactory factory, int launchFlags, string parameters)
        {
            if (shell == null)
            {
                throw new ArgumentNullException("shell");
            }

            if (debugger == null)
            {
                throw new ArgumentNullException("debugger");
            }

            if (factory == null)
            {
                throw new ArgumentNullException("factory");
            }

            var info = new VsDebugTargetInfo();
            info.cbSize = (uint)Marshal.SizeOf(info);
            info.dlo = DEBUG_LAUNCH_OPERATION.DLO_CreateProcess;

            info.bstrExe = Debugger.CurrentEditor.FileName;
            info.bstrCurDir = Path.GetDirectoryName(info.bstrExe);
            info.bstrArg = parameters; // no command line parameters
            info.bstrRemoteMachine = null; // debug locally
            info.fSendStdoutToOutputWindow = 0; // Let stdout stay with the application.
            info.clsidCustom = new Guid("{43ACAB74-8226-4920-B489-BFCF05372437}");
            // Set the launching engine the sample engine guid
            info.grfLaunch = (uint)launchFlags;
            //info.clsidPortSupplier = new Guid("FEF0E138-4F86-467D-B5FB-46888D0D1A41");

            IntPtr pInfo = Marshal.AllocCoTaskMem((int)info.cbSize);
            Marshal.StructureToPtr(info, pInfo, false);

            var eventManager = new DebugEventManager(factory, ConfigLoader, Debugger);

            if (debugger.AdviseDebugEventCallback(eventManager) != VSConstants.S_OK)
            {
                Trace.WriteLine("Failed to advise the UI of debug events.");
                if (pInfo != IntPtr.Zero)
                {
                    Marshal.FreeCoTaskMem(pInfo);
                }
                return;
            }

            try
            {
                var guid = new Guid("0EEBAE13-3B2B-434D-BDAA-9A16A84AAA8B");
                debugger.InsertBreakpointByName(ref guid, "Script");
                debugger.LaunchDebugTargets(1, pInfo);
                string outstr;
                shell.GetErrorInfo(out outstr);

                if (!String.IsNullOrWhiteSpace(outstr))
                {
                    Trace.WriteLine("Error:" + outstr);
                }
            }
            finally
            {
                if (pInfo != IntPtr.Zero)
                {
                    Marshal.FreeCoTaskMem(pInfo);
                }
            }
        }

    }
}
